package com.tina.config;


import com.tina.listener.ShiroSessionListener;
import com.tina.shiro.UserRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author PIGS-猪农·杨
 * @version 1.0
 * @date 2020/3/18 22:47
 * @effect shiro 配置类
 */
@Configuration
public class ShiroConfig {

    /**
     * 过滤器工厂
     *
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        System.out.println("启动 ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        /**
         * 拦截器 map 集合.
         */
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

        /**
         * 配置不会被拦截的链接 顺序判断
         * anon 匿名 访问
         */
        filterChainDefinitionMap.put("/static/view/login/login.html", "anon");
        filterChainDefinitionMap.put("/tiUsers/login", "anon");
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/simple/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/swagger-resources", "anon");
        filterChainDefinitionMap.put("/v2/api-docs", "anon");
        filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");
        filterChainDefinitionMap.put("/configuration/security", "anon");
        filterChainDefinitionMap.put("/configuration/ui", "anon");
        filterChainDefinitionMap.put("/tiUsers/getShiroUserInfo", "anon");
        filterChainDefinitionMap.put("/tiUsers/editUserImage", "anon");
        filterChainDefinitionMap.put("/login.html", "anon");
        filterChainDefinitionMap.put("/simple/home.html", "anon");
        filterChainDefinitionMap.put("/index.html", "authc");
        filterChainDefinitionMap.put("/tiMenu/queryMenuLeftTree", "authc");
        filterChainDefinitionMap.put("/tiOnline/queryOnlineUser", "authc");

        /**
         * 用户管理 过率链
         */
        filterChainDefinitionMap.put("/tiUsers/queryUserList", "perms[tiUsers:queryUserList]");
        filterChainDefinitionMap.put("/tiUsers/updateUserState", "perms[tiUsers:updateUserState]");
        filterChainDefinitionMap.put("/tiUsers/saveUser", "perms[tiUsers:saveUser]");
        filterChainDefinitionMap.put("/tiUsers/queryUserInfo", "perms[tiUsers:queryUserInfo]");
        filterChainDefinitionMap.put("/tiUsers/editUser", "perms[tiUsers:editUser]");
        filterChainDefinitionMap.put("/tiUsers/editUserPwd", "perms[tiUsers:editUserPwd]");

        /**
         * 角色管理过率链
         */
        filterChainDefinitionMap.put("/tiRole/queryRoleList", "perms[tiRole:queryRoleList]");
        filterChainDefinitionMap.put("/tiRole/queryUserRoleInfo", "perms[tiRole:queryUserRoleInfo]");
        filterChainDefinitionMap.put("/tiRole/queryRoleInfo", "perms[tiRole:queryRoleInfo]");
        filterChainDefinitionMap.put("/tiRole/updateRoleState", "perms[tiRole:updateRoleState]");
        filterChainDefinitionMap.put("/tiRole/saveRole", "perms[tiRole:saveRole]");
        filterChainDefinitionMap.put("/tiRole/editRole", "perms[tiRole:editRole]");
        filterChainDefinitionMap.put("/tiRole/queryRoleMenuRefListByRoleId", "perms[tiRole:queryRoleMenuRefListByRoleId]");

        /**
         * 菜单管理过率链
         */
        filterChainDefinitionMap.put("/tiMenu/updateMenuState", "perms[tiMenu:updateMenuState]");
        filterChainDefinitionMap.put("/tiMenu/queryMenuList", "perms[tiMenu:queryMenuList]");
        filterChainDefinitionMap.put("/tiMenu/queryMenuInfo", "perms[tiMenu:queryMenuInfo]");
        filterChainDefinitionMap.put("/tiMenu/updateMenu", "perms[tiMenu:updateMenu]");
        filterChainDefinitionMap.put("/tiMenu/saveMenu", "perms[tiMenu:saveMenu]");
        filterChainDefinitionMap.put("/tiMenu/queryMenuTree", "perms[tiMenu:queryMenuTree]");
        filterChainDefinitionMap.put("/tiMenu/delMenu", "perms[tiMenu:delMenu]");
        filterChainDefinitionMap.put("/tiMenu/queryMenuByMenuId", "perms[tiMenu:queryMenuByMenuId]");

        /**
         * 配置退出 过滤器,其中的具体的退出代码Shiro已经实现了
         */
        filterChainDefinitionMap.put("/logout", "logout");

        /**
         * authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
         * 过滤链定义，从上向下顺序执行，一般将/**放在最为下边
         */
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/**", "authc");

        /**
         * 如果不设置默认会自动寻找Web工程根目录下的"/login"页面
         */
        shiroFilterFactoryBean.setLoginUrl("/login.html");

        /**
         *
         * 登录成功后要跳转的链接
         * shiroFilterFactoryBean.setSuccessUrl("/index.html");
         */

        /**
         * 未授权界面
         */
        shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }


    /**
     * 身份认证realm; (账号密码校验；权限等)
     *
     * @return MyShiroRealm
     */
    @Bean
    public UserRealm myShiroRealm() {
        UserRealm myShiroRealm = new UserRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;
    }


    /**
     * 安全管理器
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        securityManager.setCacheManager(cacheManager());
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }


    /**
     * 凭证匹配器
     * （密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
     * 修改下doGetAuthenticationInfo中的代码;
     *
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

        /**
         * 散列算法:使用MD5算法
         * 加密一次
         */
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }


    /**
     * Shiro生命周期处理器 * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 顾问自动代理创建者
     *
     * @return
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 授权属性来源顾问
     *
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * redis管理
     * @return
     */
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        return redisManager;
    }

    /**
     * Redis缓存管理器
     * @return
     */
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }


    /**
     * Redis作为缓存实现
     *
     * @return
     */
    @Bean
    public RedisSessionDAO sessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }


    /**
     * 在Shiro中，SessionDao通过
     * org.apache.shiro.session.mgt.SessionManager进行管理
     * 登录时去掉jsessionId
     *
     * @return
     */
    @Bean
    public SessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        Collection<SessionListener> listeners = new ArrayList<SessionListener>();
        listeners.add(new ShiroSessionListener());
        sessionManager.setSessionListeners(listeners);
        sessionManager.setSessionDAO(sessionDAO());
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }



}
